home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / torus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  41.2 KB  |  1,644 lines

  1. /*
  2. ** Vertex Array Torus
  3. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <windows.h>
  9. #include <time.h>
  10. #include <assert.h>
  11.  
  12. #include <windows.h>
  13. #include <GL/gl.h>
  14.  
  15. #define NUM_MAJOR 32
  16. #define NUM_MINOR 24
  17.  
  18. #define X_MIN -1
  19. #define X_MAX 1
  20. #define Y_MIN -1
  21. #define Y_MAX 1
  22.  
  23. char *className = "OpenGL";
  24. char *windowName = "Vertex Array Torus";
  25. int winX, winY;
  26. int winWidth, winHeight;
  27.  
  28. #ifdef GL_SGI_cull_vertex
  29.     PFNGLCULLPARAMETERFVSGIPROC    CullParameterfvSGI;
  30. #endif
  31.  
  32. #ifdef GL_SGI_compiled_vertex_array
  33.     PFNGLLOCKARRAYSSGIPROC        LockArraysSGI;
  34.     PFNGLUNLOCKARRAYSSGIPROC        UnlockArraysSGI;
  35. #endif
  36.  
  37. HDC hDC;
  38. HGLRC hGLRC;
  39. HPALETTE hPalette;
  40. void (*idleFunc)(HDC hDC);
  41. BOOL trackingMotion = FALSE;
  42.  
  43. HMENU hMainPup, hTexturePup, hVxCullPup, hLightPup, hOutlinePup, 
  44.     hPmodePup, hDmodePup, hTexEnvPup, hShadePup, hDitherPup;
  45.  
  46. #define IDM_TEXTURE_ENABLED     100
  47. #define IDM_TEXTURE_DISABLED    101
  48. #define IDM_VXCULL_ENABLED         102
  49. #define IDM_VXCULL_DISABLED        103
  50. #define IDM_PMODE_TSTRIP    106
  51. #define IDM_PMODE_QSTRIP    107
  52. #define IDM_PMODE_LSTRIP    108
  53. #define IDM_PMODE_TRIANGLES    109
  54. #define IDM_PMODE_QUADS        110
  55. #define IDM_PMODE_LINES        111
  56. #define IDM_PMODE_POINTS    112
  57. #define IDM_PMODE_LLOOP        113
  58. #define IDM_PMODE_TFAN        114
  59. #define IDM_PMODE_POLYGON    115
  60. #define IDM_LIGHT_ENABLED         120
  61. #define IDM_LIGHT_DISABLED        121
  62. #define IDM_APPLICATION_EXIT    122
  63. #define IDM_DMODE_VERTEX    125
  64. #define IDM_DMODE_DRAW_ARRAYS    127
  65. #define IDM_DMODE_DRAW_ELEMENTS    128
  66. #define IDM_OUTLINE_ENABLED        129
  67. #define IDM_OUTLINE_DISABLED    130
  68. #define IDM_TEXENV_REPLACE      131
  69. #define IDM_TEXENV_MODULATE     132
  70. #define IDM_TEXENV_BLEND        133
  71. #define IDM_TEXENV_ADD          134
  72. #define IDM_DITHER_ENABLED      140
  73. #define IDM_DITHER_DISABLED     141
  74. #define IDM_SHADE_FLAT          150
  75. #define IDM_SHADE_SMOOTH        151
  76.  
  77. /* motion tracking globals */
  78.  
  79. GLfloat objectXform[4][4];
  80. float angle, axis[3], trans[3];
  81.  
  82. BOOL up_pressed, down_pressed, left_pressed, right_pressed;
  83.  
  84. BOOL redrawContinue = FALSE;
  85. BOOL objectSelected = FALSE;
  86. BOOL colorIndexMode = FALSE;
  87. enum MoveModes { MoveNone, MoveView, MoveObject, MovePlane };
  88. enum MoveModes mode = MoveNone;
  89.  
  90.  
  91. /* struct used to manage color ramps */
  92. struct colorIndexState {
  93.     GLfloat amb[3];    /* ambient color / bottom of ramp */
  94.     GLfloat diff[3];    /* diffuse color / middle of ramp */
  95.     GLfloat spec[3];    /* specular color / top of ramp */
  96.     GLfloat ratio;    /* ratio of diffuse to specular in ramp */
  97.     GLint indexes[3];    /* where ramp was placed in palette */
  98. };
  99.  
  100. #define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
  101. struct colorIndexState colors[] = {
  102.     {
  103.         { 0.0F, 0.0F, 0.0F },
  104.         { 1.0F, 0.0F, 0.0F },
  105.         { 1.0F, 1.0F, 1.0F },
  106.         0.75F, { 0, 0, 0 },
  107.     },
  108.     {
  109.         { 0.0F, 0.05F, 0.05F },
  110.         { 0.9F, 0.0F, 1.0F },
  111.         { 1.0F, 1.0F, 1.0F },
  112.         1.0F, { 0, 0, 0 },
  113.     },
  114.     {
  115.         { 0.0F, 0.0F, 0.0F },
  116.         { 1.0F, 0.9F, 0.1F },
  117.         { 1.0F, 1.0F, 1.0F },
  118.         0.75F, { 0, 0, 0 },
  119.     },
  120.     {
  121.         { 0.0F, 0.0F, 0.0F },
  122.         { 0.1F, 1.0F, 0.9F },
  123.         { 1.0F, 1.0F, 1.0F },
  124.         0.75F, { 0, 0, 0 },
  125.     },
  126. };
  127.  
  128. GLint lit_tex_indexes[3];
  129.  
  130. /* vtorus globals */
  131.  
  132. #define M_PI 3.14159265F
  133.  
  134. void drawTorusVarray(void);
  135. void drawTorusVarrayTex(void);
  136. void drawTorus(void);
  137.  
  138. BOOL tracking = FALSE;
  139. BOOL rgba = FALSE;
  140.  
  141. BOOL doTexture = FALSE;
  142. int texenv = IDM_TEXENV_REPLACE;
  143. BOOL doColors = FALSE;
  144. BOOL doNormals = TRUE;
  145. BOOL doLighting = TRUE;
  146. BOOL ortho = TRUE;
  147. BOOL localEye = FALSE;
  148. BOOL vxCull = FALSE;
  149. BOOL cull = TRUE;
  150. BOOL frontBuffer = FALSE;
  151. BOOL twoSided = FALSE;
  152. BOOL lightLocalViewer = FALSE;
  153. BOOL dither = TRUE;
  154. BOOL shade = GL_SMOOTH;
  155. BOOL doOutline = FALSE;
  156. GLenum cullFace = GL_BACK;
  157. BOOL vcache = TRUE;
  158. void (*drawFunction)(void) = drawTorusVarray;
  159.  
  160. static int texWidth = 128, texHeight = 128;
  161. static int needTexImage = TRUE;
  162.  
  163. int stride = 0;
  164.  
  165. static GLfloat yes[1] = {1.0F};
  166. static GLfloat no[1] = {0.0F};
  167.  
  168. int curx = 0, cury = 0;
  169. float lastPos[3] = {0.0F, 0.0F, 0.0F}; 
  170. float angle = 0.0F;
  171. float axis[3] = {0.0F, 0.0F, 0.0F};
  172.  
  173. GLfloat envColor[4] = { 0.5f, 0.3f, 0.75f, 1.0f };
  174.  
  175. void
  176. matrixIdentity(GLfloat matrix[16])
  177. {
  178.     matrix[ 0] = 1.0F;
  179.     matrix[ 1] = 0.0F;
  180.     matrix[ 2] = 0.0F;
  181.     matrix[ 3] = 0.0F;
  182.     matrix[ 4] = 0.0F;
  183.     matrix[ 5] = 1.0F;
  184.     matrix[ 6] = 0.0F;
  185.     matrix[ 7] = 0.0F;
  186.     matrix[ 8] = 0.0F;
  187.     matrix[ 9] = 0.0F;
  188.     matrix[10] = 1.0F;
  189.     matrix[11] = 0.0F;
  190.     matrix[12] = 0.0F;
  191.     matrix[13] = 0.0F;
  192.     matrix[14] = 0.0F;
  193.     matrix[15] = 1.0F;
  194. }
  195.  
  196. #define MAX_ROWS 100
  197. #define MAX_COLS 100
  198. static GLuint elements[MAX_ROWS*MAX_COLS];
  199.  
  200. static GLenum vertexFormats[] = { GL_V3F, GL_N3F_V3F};
  201. static GLenum texFormats[] = { GL_T2F_V3F, GL_T2F_N3F_V3F};
  202. static GLenum colorFormats[] = { GL_C3F_V3F, GL_C4F_N3F_V3F};
  203. static GLenum indexFormats[] = { GL_IUI_V3F_SGI, GL_IUI_N3F_V3F_SGI};
  204. static int numRGBColors[] = { 3, 4 };
  205.  
  206. /* Elements can be up to T4, C4, N3, V4 */
  207. static GLubyte interleavedData[(NUM_MAJOR+1)*NUM_MINOR*2*16*4];
  208. static int interleavedDataSize = 0;
  209. static GLenum interleavedFormat = 0;
  210.  
  211.  
  212. /* Basic primitive mode globals */
  213. static GLuint numRows, numCols;
  214. static GLuint vertexesPerFrame = 0;
  215. static GLuint primMode = 0;
  216. static GLenum primModes[] = {
  217.     GL_TRIANGLE_STRIP, 
  218.     GL_QUAD_STRIP, 
  219.     GL_LINE_STRIP,
  220.     GL_TRIANGLES,
  221.     GL_QUADS,
  222.     GL_LINES,
  223.     GL_POINTS,
  224.     GL_LINE_LOOP,
  225.     GL_TRIANGLE_FAN,
  226.     GL_POLYGON,
  227. };
  228. static char *primModeStrings[] = {
  229.     "GL_TRIANGLE_STRIP", 
  230.     "GL_QUAD_STRIP", 
  231.     "GL_LINE_STRIP",
  232.     "GL_TRIANGLES",
  233.     "GL_QUADS",
  234.     "GL_LINES",
  235.     "GL_POINTS",
  236.     "GL_LINE_LOOP",
  237.     "GL_TRIANGLE_FAN",
  238.     "GL_POLYGON",
  239. };
  240. static int primModeIDMs[] = {
  241.     IDM_PMODE_TSTRIP,
  242.     IDM_PMODE_QSTRIP,
  243.     IDM_PMODE_LSTRIP,
  244.     IDM_PMODE_TRIANGLES,
  245.     IDM_PMODE_QUADS,
  246.     IDM_PMODE_LINES,
  247.     IDM_PMODE_POINTS,
  248.     IDM_PMODE_LLOOP,
  249.     IDM_PMODE_TFAN,
  250.     IDM_PMODE_POLYGON,
  251. };
  252. static GLuint numPrimModes = sizeof(primModes)/sizeof(GLenum);
  253.  
  254. /* Draw Modes */
  255. typedef enum drawModeEnum {
  256.     DM_Vertex = 0,
  257.     DM_DrawArrays,
  258.     DM_DrawElements,
  259. } drawModeEnum;
  260.  
  261. static drawModeEnum drawModes[] = {
  262.     DM_Vertex,
  263.     DM_DrawArrays,
  264.     DM_DrawElements,
  265. };
  266. static GLuint numDrawModes = sizeof(drawModes)/sizeof(drawModeEnum);
  267. static GLuint drawMode = DM_DrawArrays;
  268. static GLuint firstDrawMode = DM_Vertex, lastDrawMode = DM_DrawElements;
  269. static char *drawModeStrings[] = {
  270.     "glVertex",
  271.     "DrawArrays",
  272.     "DrawElements",
  273. };
  274. static int drawModeIDMs[] = {
  275.     IDM_DMODE_VERTEX,
  276.     IDM_DMODE_DRAW_ARRAYS,
  277.     IDM_DMODE_DRAW_ELEMENTS,
  278. };
  279.  
  280.  
  281. int
  282. getFormatSize(GLenum format)
  283. {
  284.     switch (format) {
  285.     case GL_N3F_V3F:
  286.     case GL_C3F_V3F:
  287.         return 24;
  288.     case GL_T2F_N3F_V3F:
  289.         return 32;
  290.     case GL_C4F_N3F_V3F:
  291.         return 40;
  292.     case GL_T2F_V3F:
  293.         return 20;
  294.     case GL_IUI_V3F_SGI:
  295.         return 16;
  296.     case GL_IUI_N3F_V3F_SGI:
  297.         return 28;
  298.     }
  299.     return 0;
  300. }
  301.  
  302. void
  303. setCheckedTexture(void)
  304. {
  305.     int texSize;
  306.     void *textureBuf;
  307.     int i,j;
  308.  
  309.     if (!needTexImage) return;
  310.  
  311.     /* malloc for rgba as worst case */
  312.     texSize = texWidth*texHeight*4;
  313.  
  314.     textureBuf = malloc(texSize);
  315.     if (NULL == textureBuf) return;
  316.  
  317.     if (rgba) {
  318.     GLubyte *p = (GLubyte *)textureBuf;
  319.     for (i=0; i < texWidth; i++) {
  320.         for (j=0; j < texHeight; j++) {
  321.         if ((i ^ j) & 8) {
  322.             p[0] = 0xff; p[1] = 0xff; p[2] = 0xff; p[3] = 0xff;
  323.         } else {
  324.             p[0] = 0x08; p[1] = 0x08; p[2] = 0x08; p[3] = 0xff;
  325.         }
  326.         p += 4;
  327.         }
  328.     }
  329.     glTexImage2D(GL_TEXTURE_2D, 0, 3, texWidth, texHeight, 
  330.             0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuf);
  331.     } else {
  332.     GLubyte *pBuf = (GLubyte *)textureBuf;
  333.     GLubyte c0, c1;
  334.  
  335.     if (texenv == IDM_TEXENV_REPLACE) {
  336.         c0 = colors[0].indexes[1];
  337.         c1 = colors[2].indexes[2];
  338.     } else {
  339.         c0 = colors[0].indexes[0] & 0xff;
  340.         c1 = colors[2].indexes[0] & 0xff;
  341.     }
  342.  
  343.     for (i=0; i<texHeight; ++i) {
  344.         for (j=0; j<texWidth; ++j) {
  345.         if ((i ^ j) & 8) {
  346.             *pBuf = c0;
  347.         } else {
  348.             *pBuf = c1;
  349.         }
  350.         pBuf ++;
  351.         }
  352.     }
  353.     glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
  354.              texWidth, texHeight, 0,
  355.               GL_COLOR_INDEX, GL_UNSIGNED_BYTE, textureBuf);
  356.     }
  357.     free(textureBuf);
  358.     needTexImage = FALSE;
  359. }
  360.  
  361. void
  362. calcTorusData(void)
  363. {
  364.     static GLubyte *basePtr;
  365.     int numMajor = NUM_MAJOR;
  366.     int numMinor = NUM_MINOR;
  367.     int padding;
  368.     float majorRadius = 0.6F;
  369.     float minorRadius = 0.2F;
  370.     double majorStep = 2.0F*M_PI / numMajor;
  371.     double minorStep = 2.0F*M_PI / numMinor;
  372.     int i, j;
  373.     int count;
  374.     float red, green, blue, colorStep = 0.01F;
  375.     float texS, texT, texStep_s, texStep_t;
  376.     int formatSize;
  377.     int colorOffset, normalOffset, vertexOffset;
  378.     int numColors;
  379.  
  380.     formatSize = getFormatSize(interleavedFormat);
  381.     assert(0 != formatSize);
  382.  
  383.     if (doColors) {
  384.     numColors = rgba ? numRGBColors[doNormals] : 1;
  385.     } else {
  386.     numColors = 0;
  387.     }
  388.  
  389.     colorOffset = doTexture ? 2*sizeof(GLfloat) : 0;
  390.     assert(sizeof(GLfloat) == sizeof(GLuint));
  391.     normalOffset = colorOffset + numColors*sizeof(GLfloat);
  392.     vertexOffset = doNormals ? normalOffset + 3*sizeof(GLfloat) 
  393.                  : normalOffset;
  394.  
  395.     stride = formatSize;
  396.     padding = 0;
  397.  
  398.     if (doTexture) {
  399.     texStep_s = 1.0F/numMajor;
  400.     texStep_t = 1.0F/numMinor;
  401.     texS = texT = 0.0F;
  402.     }
  403.  
  404.     count = (numMajor+1)*(numMinor+1);
  405.     for (i=0; i<count; i++) elements[i] = i;
  406.  
  407.     basePtr = interleavedData;
  408.  
  409.     for (i=0; i <= numMajor; ++i) {
  410.     double a0;
  411.     GLfloat x0;
  412.     GLfloat y0;
  413.  
  414.     if (i == numMajor) {
  415.         a0 = 0;
  416.     } else {
  417.         a0 = i * majorStep;
  418.     } 
  419.     x0 = (GLfloat)cos(a0);
  420.     y0 = (GLfloat)sin(a0);
  421.  
  422.     if (doColors) {
  423.         if (rgba) {
  424.         red = i%3 * 0.1F;
  425.         green = (i+1)%3 * 0.1F;
  426.         blue = (i+2)%3 * 0.1F;
  427.         } else {
  428.         red = (GLfloat)(i & 0x7);
  429.         }
  430.     } 
  431.  
  432.     for (j=0; j<=numMinor; j++) {
  433.         double b = j * minorStep;
  434.         GLfloat c = (GLfloat)cos(b);
  435.         GLfloat r = minorRadius * c + majorRadius;
  436.         GLfloat z = minorRadius * (GLfloat)sin(b);
  437.         GLfloat *vertexPtr;
  438.  
  439.         if (doTexture) {
  440.         GLfloat *texPtr = (GLfloat*)(basePtr);
  441.         texPtr[0] = texS;
  442.         texPtr[1] = texT;
  443.         }
  444.         if (doColors) {
  445.         /* color */
  446.         if (rgba) {
  447.             GLfloat *colorPtr = (GLfloat*)(basePtr+colorOffset);
  448.             colorPtr[0] = red;
  449.             colorPtr[1] = green;
  450.             colorPtr[2] = blue;
  451.             if (numColors > 3) {
  452.             colorPtr[3] = 1.0F; /* alpha */
  453.             }
  454.             red = 1.0F-red; 
  455.         } else {
  456.             GLuint *colorPtr = (GLuint*)(basePtr+colorOffset);
  457.             colorPtr[0] = (GLuint)red;
  458.         }
  459.         }
  460.         if (doNormals) {
  461.         GLfloat *normalPtr = (GLfloat*)(basePtr+normalOffset);
  462.         normalPtr[0] = x0*c;
  463.         normalPtr[1] = y0*c;
  464.         normalPtr[2] = z/minorRadius;
  465.         } 
  466.         /* vertex */
  467.         vertexPtr = (GLfloat*)(basePtr+vertexOffset);
  468.         vertexPtr[0] = x0*r;
  469.         vertexPtr[1] = y0*r;
  470.         vertexPtr[2] = z;
  471.  
  472.         if (doTexture) {
  473.            texT += texStep_t;
  474.         }
  475.  
  476.         basePtr += stride;
  477.     }
  478.     if (doTexture) {
  479.        texS += texStep_s;
  480.        texT = 0.0F;
  481.     }
  482.     }
  483.     interleavedDataSize = (numMajor+1)*numMinor*stride;
  484.     vertexesPerFrame = numMajor*numMinor;
  485. }
  486.  
  487.  
  488. void userSettings(int doPrint)
  489. {
  490.     static GLfloat eyeDir[4] = {0.0F, 0.0F, 1.0F, 0.0F};
  491.     static GLfloat eyePos[4] = {0.0F, 0.0F, 0.0F, 1.0F};
  492.  
  493.     /* if lighting or no colors or texture, need normals */
  494.     if (doLighting || !(doColors || doTexture)) {
  495.     doNormals = 1;
  496.     }
  497.     if (doColors) {
  498.     doLighting = FALSE;
  499.     doTexture = FALSE;
  500.     }
  501.     if ((DM_DrawArrays == drawModes[drawMode])) {
  502.     drawMode = DM_DrawElements - firstDrawMode;
  503.     }
  504.  
  505.     /* set up interleaved format */
  506.     if (doColors) {
  507.     if (rgba) {
  508.         interleavedFormat = colorFormats[doNormals];
  509.     } else {
  510.         interleavedFormat = indexFormats[doNormals];
  511.     }
  512.     } else if (doTexture) {
  513.     interleavedFormat = texFormats[doNormals];
  514.     } else {
  515.     interleavedFormat = vertexFormats[doNormals];
  516.     }
  517.  
  518.     switch ( texenv )
  519.     {
  520.     case IDM_TEXENV_REPLACE:
  521.     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
  522.     break;
  523.     case IDM_TEXENV_MODULATE:
  524.     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  525.     break;
  526.     case IDM_TEXENV_BLEND:
  527.     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND );
  528.     glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor );
  529.     break;
  530.     case IDM_TEXENV_ADD:
  531.     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
  532.     break;
  533.     }
  534.  
  535.     if ( dither )
  536.         glEnable( GL_DITHER );
  537.     else
  538.         glDisable( GL_DITHER );
  539.  
  540.     if (twoSided) {
  541.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
  542.     } else {
  543.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
  544.     }
  545.  
  546.     if (lightLocalViewer) {
  547.         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  548.     } else {
  549.         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
  550.     }
  551.  
  552.     if (doLighting) {
  553.     glEnable(GL_LIGHTING);
  554.     glEnable(GL_LIGHT0);
  555.     glShadeModel( shade );
  556.     if (!rgba) {
  557.         glIndexi(colors[0].indexes[1]);
  558.     }
  559.     } else {
  560.     glDisable(GL_LIGHTING);
  561.     glDisable(GL_LIGHT0);
  562.     glShadeModel( shade );
  563.     if (rgba) {
  564.         glColor3f(1.0F,1.0F,1.0F);
  565.     } else {
  566.         /* this moves the value up the ramp from the texel */
  567.         glIndexi(colors[0].indexes[1] - colors[0].indexes[0]);
  568.     }
  569.     }
  570.     glMatrixMode(GL_PROJECTION);
  571.     glLoadIdentity();
  572.     if (ortho) {
  573.     glOrtho(-1, 1, -1, 1, 1, 3);
  574.     } else {
  575.     glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
  576.     }
  577.  
  578. #ifdef GL_SGI_cull_vertex
  579.     if (CullParameterfvSGI) {
  580.     if (localEye) {
  581.         (*CullParameterfvSGI)(GL_CULL_VERTEX_EYE_POSITION_SGI, eyePos);
  582.     } else {
  583.         (*CullParameterfvSGI)(GL_CULL_VERTEX_EYE_POSITION_SGI, eyeDir);
  584.     }
  585.     }
  586. #endif
  587.  
  588.     glMatrixMode(GL_MODELVIEW);
  589.     glLoadIdentity();
  590.     glTranslatef(0.0F, 0.0F, -2.0F);
  591.  
  592.     calcTorusData();
  593.     switch(drawModes[drawMode]) {
  594.     case DM_DrawArrays:         /* not supported yet */
  595.     case DM_DrawElements:
  596.     if (doTexture) {
  597.         drawFunction = drawTorusVarrayTex;
  598.     } else {
  599.         drawFunction = drawTorusVarray;
  600.     }
  601.     break;
  602.     case DM_Vertex:
  603.     drawFunction = drawTorus;
  604.     break;
  605.     }
  606.  
  607.  
  608.     if (frontBuffer) {
  609.     glDrawBuffer(GL_FRONT);
  610.     } else {
  611.     glDrawBuffer(GL_BACK);
  612.     }
  613.  
  614.     if (doTexture) {
  615.     setCheckedTexture();
  616.     glEnable(GL_TEXTURE_2D);
  617.     glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, lit_tex_indexes);
  618.     glMaterialiv(GL_BACK, GL_COLOR_INDEXES, lit_tex_indexes);
  619.     } else {
  620.     glDisable(GL_TEXTURE_2D);
  621.     glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[0].indexes);
  622.     glMaterialiv(GL_BACK, GL_COLOR_INDEXES, colors[2].indexes);
  623.     }
  624.  
  625. #ifdef GL_SGI_cull_vertex
  626.     if (vxCull) {
  627.     glEnable(GL_CULL_VERTEX_SGI);
  628.     } else {
  629.     glDisable(GL_CULL_VERTEX_SGI);
  630.     }
  631. #endif
  632.  
  633.     if (cull) {
  634.     glEnable(GL_CULL_FACE);
  635.     glCullFace(cullFace);
  636.     } else {
  637.     glDisable(GL_CULL_FACE);
  638.     }
  639.  
  640.     if (doOutline) {
  641.     glEnable(GL_POLYGON_OFFSET_FILL);
  642.     glPolygonOffset(0.0f, 1.0f);
  643.     } else {
  644.     glDisable(GL_POLYGON_OFFSET_FILL);
  645.     }
  646.  
  647.     {
  648.     unsigned int i;
  649.     MENUITEMINFO miinfo;
  650.  
  651.     miinfo.cbSize = sizeof(miinfo);
  652.     miinfo.fMask = MIIM_STATE;
  653.  
  654.     miinfo.fState = MFS_UNCHECKED;
  655.     SetMenuItemInfo( hTexEnvPup, IDM_TEXENV_REPLACE, FALSE, &miinfo);
  656.     if (rgba) {
  657.         SetMenuItemInfo( hTexEnvPup, IDM_TEXENV_MODULATE, FALSE, &miinfo);
  658.         SetMenuItemInfo( hTexEnvPup, IDM_TEXENV_BLEND, FALSE, &miinfo);
  659.     } else {
  660.         SetMenuItemInfo( hTexEnvPup, IDM_TEXENV_ADD, FALSE, &miinfo);
  661.     }
  662.     miinfo.fState = MFS_CHECKED;
  663.     SetMenuItemInfo( hTexEnvPup, texenv, FALSE, &miinfo );
  664.  
  665.     miinfo.fState = MFS_UNCHECKED;
  666.     SetMenuItemInfo( hShadePup, IDM_SHADE_FLAT, FALSE, &miinfo );
  667.     SetMenuItemInfo( hShadePup, IDM_SHADE_SMOOTH, FALSE, &miinfo );
  668.     miinfo.fState = MFS_CHECKED;
  669.     if ( shade == GL_FLAT )
  670.         SetMenuItemInfo( hShadePup, IDM_SHADE_FLAT, FALSE, &miinfo );
  671.     else
  672.         SetMenuItemInfo( hShadePup, IDM_SHADE_SMOOTH, FALSE, &miinfo );
  673.  
  674.     miinfo.fState = MFS_UNCHECKED;
  675.     SetMenuItemInfo( hDitherPup, IDM_DITHER_ENABLED, FALSE, &miinfo );
  676.     SetMenuItemInfo( hDitherPup, IDM_DITHER_DISABLED, FALSE, &miinfo );
  677.     miinfo.fState = MFS_CHECKED;
  678.     if ( dither )
  679.         SetMenuItemInfo( hDitherPup, IDM_DITHER_ENABLED, FALSE, &miinfo );
  680.     else
  681.         SetMenuItemInfo( hDitherPup, IDM_DITHER_DISABLED, FALSE, &miinfo );
  682.  
  683.     if (vxCull) {
  684.         miinfo.fState = MFS_CHECKED;
  685.         SetMenuItemInfo(hVxCullPup, IDM_VXCULL_ENABLED, FALSE, &miinfo);
  686.         miinfo.fState = MFS_UNCHECKED;
  687.         SetMenuItemInfo(hVxCullPup, IDM_VXCULL_DISABLED, FALSE, &miinfo);
  688.     } else {
  689.         miinfo.fState = MFS_CHECKED;
  690.         SetMenuItemInfo(hVxCullPup, IDM_VXCULL_DISABLED, FALSE, &miinfo);
  691.         miinfo.fState = MFS_UNCHECKED;
  692.         SetMenuItemInfo(hVxCullPup, IDM_VXCULL_ENABLED, FALSE, &miinfo);
  693.     }
  694.     if (doLighting) {
  695.         miinfo.fState = MFS_CHECKED;
  696.         SetMenuItemInfo(hLightPup, IDM_LIGHT_ENABLED, FALSE, &miinfo);
  697.         miinfo.fState = MFS_UNCHECKED;
  698.         SetMenuItemInfo(hLightPup, IDM_LIGHT_DISABLED, FALSE, &miinfo);
  699.     } else {
  700.         miinfo.fState = MFS_CHECKED;
  701.         SetMenuItemInfo(hLightPup, IDM_LIGHT_DISABLED, FALSE, &miinfo);
  702.         miinfo.fState = MFS_UNCHECKED;
  703.         SetMenuItemInfo(hLightPup, IDM_LIGHT_ENABLED, FALSE, &miinfo);
  704.     }
  705.     if (doTexture) {
  706.         miinfo.fState = MFS_CHECKED;
  707.         SetMenuItemInfo(hTexturePup, IDM_TEXTURE_ENABLED, FALSE, &miinfo);
  708.         miinfo.fState = MFS_UNCHECKED;
  709.         SetMenuItemInfo(hTexturePup, IDM_TEXTURE_DISABLED, FALSE, &miinfo);
  710.     } else {
  711.         miinfo.fState = MFS_CHECKED;
  712.         SetMenuItemInfo(hTexturePup, IDM_TEXTURE_DISABLED, FALSE, &miinfo);
  713.         miinfo.fState = MFS_UNCHECKED;
  714.         SetMenuItemInfo(hTexturePup, IDM_TEXTURE_ENABLED, FALSE, &miinfo);
  715.     }
  716.     if (doOutline) {
  717.         miinfo.fState = MFS_CHECKED;
  718.         SetMenuItemInfo(hOutlinePup, IDM_OUTLINE_ENABLED, FALSE, &miinfo);
  719.         miinfo.fState = MFS_UNCHECKED;
  720.         SetMenuItemInfo(hOutlinePup, IDM_OUTLINE_DISABLED, FALSE, &miinfo);
  721.     } else {
  722.         miinfo.fState = MFS_CHECKED;
  723.         SetMenuItemInfo(hOutlinePup, IDM_OUTLINE_DISABLED, FALSE, &miinfo);
  724.         miinfo.fState = MFS_UNCHECKED;
  725.         SetMenuItemInfo(hOutlinePup, IDM_OUTLINE_ENABLED, FALSE, &miinfo);
  726.     }
  727.     for (i=0; i < numPrimModes; i++) {
  728.         miinfo.fState = (i == primMode) ? MFS_CHECKED : MFS_UNCHECKED;
  729.         SetMenuItemInfo(hPmodePup, primModeIDMs[i], FALSE, &miinfo);
  730.     }
  731.     for (i=0; i < numDrawModes; i++) {
  732.         miinfo.fState = (i == drawMode) ? MFS_CHECKED : MFS_UNCHECKED;
  733.         SetMenuItemInfo(hDmodePup, drawModeIDMs[i], FALSE, &miinfo);
  734.     }
  735.     }
  736. }
  737.  
  738.  
  739. void
  740. drawTorusVarrayTex(void)
  741. {
  742.     int numMajor = NUM_MAJOR;
  743.     int numMinor = NUM_MINOR;
  744.     int i, j;
  745.     int curElement = 0;
  746.     int count;
  747.  
  748.     count = (numMajor+1)*(numMinor+1);
  749.  
  750.     glInterleavedArrays(interleavedFormat, stride, interleavedData);
  751.  
  752. #ifdef GL_SGI_compiled_vertex_array
  753.     if (LockArraysSGI)
  754.     (*LockArraysSGI)(0, count);
  755. #endif
  756.  
  757.     {
  758.     int numElements;
  759.     int majorPos = 0, majorPos1 = 0;
  760.     for (i=0; i<numMajor; ++i) {
  761.         numElements = 0;
  762.         for (j=0; j<=numMinor; ++j) {
  763.         majorPos = i*(numMinor+1); /* this row */
  764.         majorPos1 = majorPos + numMinor+1; /* next row */
  765.         elements[numElements++] = majorPos + j;
  766.         elements[numElements++] = majorPos1 + j;
  767.         }
  768.         glDrawElements(GL_TRIANGLE_STRIP, numElements, 
  769.                 GL_UNSIGNED_INT, elements);
  770.     }
  771.     }
  772.  
  773. #ifdef GL_SGI_compiled_vertex_array
  774.     if (LockArraysSGI)
  775.     (*UnlockArraysSGI)();
  776. #endif
  777. }
  778.  
  779. void
  780. drawTorusVarray(void)
  781. {
  782.     int numMajor = NUM_MAJOR;
  783.     int numMinor = NUM_MINOR;
  784.     int i, j;
  785.     int curElement = 0;
  786.     int count;
  787.  
  788.     count = (numMajor+1)*(numMinor+1);
  789.  
  790.     glInterleavedArrays(interleavedFormat, stride, interleavedData);
  791.  
  792. #ifdef GL_SGI_compiled_vertex_array
  793.     if (LockArraysSGI)
  794.     (*LockArraysSGI)(0, count);
  795. #endif
  796.  
  797.     {
  798.     int numElements;
  799.     int majorPos = 0, majorPos1 = 0;
  800.     for (i=0; i<numMajor; ++i) {
  801.         numElements = 0;
  802.         for (j=0; j<=numMinor; j++) {
  803.         majorPos = i*(numMinor+1);         /* this row */
  804.         majorPos1 = majorPos + numMinor+1;     /* next row */
  805.         elements[numElements++] = majorPos + j;
  806.         elements[numElements++] = majorPos1 + j;
  807.         }
  808.         glDrawElements(GL_TRIANGLE_STRIP, numElements, 
  809.                 GL_UNSIGNED_INT, elements);
  810.     }
  811.     }
  812.  
  813. #ifdef GL_SGI_compiled_vertex_array
  814.     if (LockArraysSGI)
  815.     (*UnlockArraysSGI)();
  816. #endif
  817. }
  818.  
  819. void
  820. drawTorus(void)
  821. {
  822.     int numMajor = NUM_MAJOR;
  823.     int numMinor = NUM_MINOR;
  824.     float majorRadius = 0.6F;
  825.     float minorRadius = 0.2F;
  826.     double majorStep = 2.0F*M_PI / numMajor;
  827.     double minorStep = 2.0F*M_PI / numMinor;
  828.     int i, j;
  829.  
  830.     for (i=0; i<numMajor; ++i) {
  831.     double a0 = i * majorStep;
  832.     double a1 = a0 + majorStep;
  833.     GLfloat x0 = (GLfloat)cos(a0);
  834.     GLfloat y0 = (GLfloat)sin(a0);
  835.     GLfloat x1 = (GLfloat)cos(a1);
  836.     GLfloat y1 = (GLfloat)sin(a1);
  837.  
  838.     glBegin(GL_TRIANGLE_STRIP);
  839.     for (j=0; j<=numMinor; ++j) {
  840.         double b = j * minorStep;
  841.         GLfloat c = (GLfloat)cos(b);
  842.         GLfloat r = minorRadius * c + majorRadius;
  843.         GLfloat z = minorRadius * (GLfloat)sin(b);
  844.  
  845.         glNormal3f(x0*c, y0*c, z/minorRadius);
  846.         glTexCoord2f(i/(GLfloat) numMajor, j/(GLfloat) numMinor);
  847.         glVertex3f(x0*r, y0*r, z);
  848.  
  849.         glNormal3f(x1*c, y1*c, z/minorRadius);
  850.         glTexCoord2f((i+1)/(GLfloat) numMajor, j/(GLfloat) numMinor);
  851.         glVertex3f(x1*r, y1*r, z);
  852.     }
  853.     glEnd();
  854.     }
  855. }
  856.  
  857. void 
  858. init(HDC hDC)
  859. {
  860.     GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
  861.     GLfloat matAmb[4] = { 0.01F, 0.01F, 0.01F, 1.00F };
  862.     GLfloat matDiff[4] = { 0.65F, 0.05F, 0.20F, 0.60F };
  863.     GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F };
  864.     GLfloat matShine = 20.00F;
  865.  
  866.     /* Init extensions */
  867. #ifdef GL_SGI_cull_vertex
  868.     CullParameterfvSGI = (void *) wglGetProcAddress("glCullParameterfvSGI");
  869. #endif
  870.  
  871. #ifdef GL_SGI_compiled_vertex_array
  872.     LockArraysSGI = (void *) wglGetProcAddress("glLockArraysSGI");
  873.     if (LockArraysSGI) {
  874.     UnlockArraysSGI = (void *) wglGetProcAddress("glUnlockArraysSGI");
  875.     assert(NULL != UnlockArraysSGI);
  876.     } 
  877. #endif
  878.  
  879.     glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  880.     glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
  881.     glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
  882.     glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
  883.     glMaterialf(GL_FRONT, GL_SHININESS, matShine);
  884.     if (!rgba) {
  885.     glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[0].indexes);
  886.     glMaterialiv(GL_BACK, GL_COLOR_INDEXES, colors[2].indexes);
  887.     glClearIndex((GLfloat) (colors[1].indexes[0] + 
  888.         (colors[1].indexes[1] - colors[1].indexes[0])/2));
  889.     }
  890.  
  891.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  892.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  893.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  894.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  895.  
  896.     glEnable(GL_DEPTH_TEST);
  897.  
  898.     matrixIdentity((GLfloat *) objectXform);
  899.  
  900.     userSettings(1);
  901.  
  902.     glMatrixMode(GL_MODELVIEW);
  903.  
  904. }
  905.  
  906. void
  907. resize(HDC hDC)
  908. {
  909.     glViewport(0, 0, winWidth, winHeight);
  910. }
  911.  
  912. void
  913. doRedraw(HDC hDC)
  914. {
  915.     if ( down_pressed )  trans[1] -= 0.05F;
  916.     if ( up_pressed )    trans[1] += 0.05F;
  917.     if ( left_pressed )  trans[0] -= 0.05F;
  918.     if ( right_pressed ) trans[0] += 0.05F;
  919.  
  920.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  921.  
  922.     /* update transformations */
  923.     if (mode == MoveObject || mode == MoveView) {
  924.     glPushMatrix();
  925.     glLoadIdentity();
  926.     glRotatef(angle, axis[0], axis[1], axis[2]);
  927.     glMultMatrixf((GLfloat *) objectXform);
  928.     glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
  929.     glPopMatrix();
  930.     }
  931.     glPushMatrix();
  932.     glTranslatef( trans[0], trans[1], trans[2] );
  933.     glMultMatrixf((GLfloat *) objectXform);
  934.  
  935.     (*drawFunction)();
  936.     if (doOutline) {
  937.     GLfloat color[4];
  938.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  939.     if (doLighting)
  940.         glDisable(GL_LIGHTING);
  941.     if (doTexture)
  942.         glDisable(GL_TEXTURE_2D);
  943.     if (rgba) {
  944.         glGetFloatv(GL_CURRENT_COLOR, color);
  945.         glColor3f(0.0f, 0.0f, 0.0f);
  946.     } else {
  947.         glGetFloatv(GL_CURRENT_INDEX, color);
  948.         glIndexi(0);
  949.     }
  950.     (*drawFunction)();
  951.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  952.     if (doLighting)
  953.         glEnable(GL_LIGHTING);
  954.     if (doTexture)
  955.         glEnable(GL_TEXTURE_2D);
  956.     if (rgba) {
  957.         glColor4fv(color);
  958.     } else {
  959.         glIndexfv(color);
  960.     }
  961.     }
  962.     glPopMatrix();
  963.  
  964.     SwapBuffers(hDC);
  965.  
  966. }
  967.  
  968. /*****************************************************************/
  969.  
  970. void
  971. idleRedraw(HDC hDC)
  972. {
  973.     if (!redrawContinue) {
  974.         idleFunc = NULL;
  975.     }
  976.     doRedraw(hDC);
  977. }
  978.  
  979. void
  980. redraw(HDC hDC)
  981. {
  982.     if (!idleFunc) {
  983.     if (redrawContinue) {
  984.         idleFunc = idleRedraw;
  985.     } else {
  986.         doRedraw(hDC);
  987.     }
  988.     }
  989. }
  990.  
  991. /*****************************************************************/
  992.  
  993.  
  994. /* these functions implement a simple trackball-like motion control */
  995. float lastPos[3];
  996. DWORD lastTime;
  997. int startX, startY;
  998.  
  999. void
  1000. ptov(int x, int y, int width, int height, float v[3])
  1001. {
  1002.     float d, a;
  1003.  
  1004.     /* project x,y onto a hemi-sphere centered within width, height */
  1005.     v[0] = (2.0F*x - width) / width;
  1006.     v[1] = (height - 2.0F*y) / height;
  1007.     d = (float) sqrt(v[0]*v[0] + v[1]*v[1]);
  1008.     v[2] = (float) cos((M_PI/2.0F) * ((d < 1.0F) ? d : 1.0F));
  1009.     a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  1010.     v[0] *= a;
  1011.     v[1] *= a;
  1012.     v[2] *= a;
  1013. }
  1014.  
  1015. void
  1016. startMotion(HDC hDC, DWORD time, int button, int x, int y)
  1017. {
  1018.     if (button == 1) {
  1019.     if (objectSelected) {
  1020.         mode = MoveObject;
  1021.     } else {
  1022.         mode = MoveView;
  1023.     }
  1024.     } else if (button == 2) {
  1025.     mode = MovePlane;
  1026.     } else {
  1027.     return;
  1028.     }
  1029.  
  1030.     trackingMotion = TRUE;
  1031.     redrawContinue = FALSE;
  1032.     startX = x;
  1033.     startY = y;
  1034.     ptov(x, y, winWidth, winHeight, lastPos);
  1035. }
  1036.  
  1037. void
  1038. stopMotion(HDC hDC, DWORD time, int button, int x, int y)
  1039. {
  1040.     if ((button == 1 && mode == MoveView) ||
  1041.     (button == 1 && mode == MoveObject) ||
  1042.     (button == 2 && mode == MovePlane))
  1043.     {
  1044.     trackingMotion = FALSE;
  1045.     } else {
  1046.     return;
  1047.     }
  1048.  
  1049.     if (startX != x || startY != y) {
  1050.     redrawContinue = TRUE;
  1051.     } else {
  1052.     angle = 0.0F;
  1053.     redrawContinue = FALSE;
  1054.     }
  1055.     if (!redrawContinue) {
  1056.     mode = MoveNone;
  1057.     }
  1058.     redraw(hDC);
  1059. }
  1060.  
  1061. void
  1062. trackMotion(HDC hDC, DWORD time, int x, int y)
  1063. {
  1064.     if (trackingMotion) {
  1065.     float curPos[3], dx, dy, dz;
  1066.  
  1067.     ptov(x, y, winWidth, winHeight, curPos);
  1068.  
  1069.     dx = curPos[0] - lastPos[0];
  1070.     dy = curPos[1] - lastPos[1];
  1071.     dz = curPos[2] - lastPos[2];
  1072.     angle = 90.0F * (float) sqrt(dx*dx + dy*dy + dz*dz);
  1073.  
  1074.     axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
  1075.     axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
  1076.     axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
  1077.  
  1078.     lastPos[0] = curPos[0];
  1079.     lastPos[1] = curPos[1];
  1080.     lastPos[2] = curPos[2];
  1081.     redraw(hDC);
  1082.     }
  1083. }
  1084.  
  1085. /*****************************************************************/
  1086.  
  1087. void
  1088. setupPalette(HDC hDC)
  1089. {
  1090.     PIXELFORMATDESCRIPTOR pfd;
  1091.     LOGPALETTE* pPal;
  1092.     int pixelFormat = GetPixelFormat(hDC);
  1093.     int paletteSize;
  1094.  
  1095.     (void) DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  1096.     if (!(pfd.dwFlags & PFD_NEED_PALETTE || pfd.iPixelType == PFD_TYPE_COLORINDEX)) {
  1097.     return;
  1098.     }
  1099.  
  1100.     paletteSize = 1 << pfd.cColorBits;
  1101.     pPal = (LOGPALETTE*)
  1102.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  1103.     pPal->palVersion = 0x300;
  1104.     pPal->palNumEntries = paletteSize;
  1105.  
  1106.     /* start with a copy of the current system palette */
  1107.     (void) GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  1108.  
  1109.     if (pfd.iPixelType == PFD_TYPE_RGBA) {
  1110.     /* fill in an RGBA color palette */
  1111.     int redMask = (1 << pfd.cRedBits) - 1;
  1112.     int greenMask = (1 << pfd.cGreenBits) - 1;
  1113.     int blueMask = (1 << pfd.cBlueBits) - 1;
  1114.     int i;
  1115.  
  1116.     for (i=0; i<paletteSize; ++i) {
  1117.         pPal->palPalEntry[i].peRed =
  1118.             (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
  1119.         pPal->palPalEntry[i].peGreen =
  1120.             (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
  1121.         pPal->palPalEntry[i].peBlue =
  1122.             (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
  1123.         pPal->palPalEntry[i].peFlags = 0;
  1124.     }
  1125.     } else {
  1126.     /* fill in a Color Index ramp color palette */
  1127.     int numRamps = NUM_COLORS;
  1128.     int rampSize = (paletteSize - 20) / numRamps;
  1129.     int extra = (paletteSize - 20) - (numRamps * rampSize);
  1130.     int i, r;
  1131.  
  1132.     for (r=0; r<numRamps; ++r) {
  1133.         int rampBase = r * rampSize + 10;
  1134.         PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
  1135.         int diffSize = (int) (rampSize * colors[r].ratio);
  1136.         int specSize = rampSize - diffSize;
  1137.  
  1138.         for (i=0; i<rampSize; ++i) {
  1139.         GLfloat *c0, *c1;
  1140.         GLint a;
  1141.  
  1142.         if (i < diffSize) {
  1143.             c0 = colors[r].amb;
  1144.             c1 = colors[r].diff;
  1145.             a = (i * 255) / (diffSize - 1);
  1146.         } else {
  1147.             c0 = colors[r].diff;
  1148.             c1 = colors[r].spec;
  1149.             a = ((i - diffSize) * 255) / (specSize - 1);
  1150.         }
  1151.  
  1152.         pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]);
  1153.         pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]);
  1154.         pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]);
  1155.         pe[i].peFlags = PC_NOCOLLAPSE;
  1156.         }
  1157.  
  1158.         colors[r].indexes[0] = rampBase;
  1159.         colors[r].indexes[1] = rampBase + (diffSize-1);
  1160.         colors[r].indexes[2] = rampBase + (rampSize-1);
  1161.     }
  1162.     lit_tex_indexes[0] = 0;
  1163.     lit_tex_indexes[1] = (GLint)(rampSize*colors[0].ratio)-1;
  1164.     lit_tex_indexes[2] = rampSize-1;
  1165.  
  1166.     for (i=0; i<extra; ++i) {
  1167.         int index = numRamps*rampSize+10+i;
  1168.         PALETTEENTRY *pe = &pPal->palPalEntry[index];
  1169.  
  1170.         pe->peRed = (BYTE) 0;
  1171.         pe->peGreen = (BYTE) 0;
  1172.         pe->peBlue = (BYTE) 0;
  1173.         pe->peFlags = PC_NOCOLLAPSE;
  1174.     }
  1175.     }
  1176.  
  1177.     hPalette = CreatePalette(pPal);
  1178.     free(pPal);
  1179.  
  1180.     if (hPalette) {
  1181.     SelectPalette(hDC, hPalette, FALSE);
  1182.     RealizePalette(hDC);
  1183.     }
  1184. }
  1185.  
  1186. void
  1187. setupDC(HDC hDC)
  1188. {
  1189.     byte pixelType = rgba ? PFD_TYPE_RGBA : PFD_TYPE_COLORINDEX;
  1190.     PIXELFORMATDESCRIPTOR pfd = {
  1191.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  1192.     1,                /* version num */
  1193.     PFD_DRAW_TO_WINDOW |        /* support window */
  1194.     PFD_SUPPORT_OPENGL |        /* support OpenGL */
  1195.     PFD_DOUBLEBUFFER,        /* support double buffering */
  1196.     pixelType,            /* RGBA type */
  1197.     8,                /* 8-bit color depth */
  1198.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  1199.     0,                /* no alpha buffer */
  1200.     0,                /* alpha bits (ignored) */
  1201.     0,                /* no accumulation buffer */
  1202.     0, 0, 0, 0,            /* accum bits (ignored) */
  1203.     16,                /* 16-bit depth buffer */
  1204.     0,                /* no stencil buffer */
  1205.     0,                /* no auxiliary buffers */
  1206.     PFD_MAIN_PLANE,            /* main layer */
  1207.     0,                /* reserved */
  1208.     0, 0, 0,            /* no layer, visible, damage masks */
  1209.     };
  1210.     int SelectedPixelFormat;
  1211.     BOOL retVal;
  1212.  
  1213.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  1214.     if (SelectedPixelFormat == 0) {
  1215.     (void) MessageBox(WindowFromDC(hDC),
  1216.         "Failed to find acceptable pixel format.",
  1217.         "OpenGL application error",
  1218.         MB_ICONERROR | MB_OK);
  1219.     exit(1);
  1220.     }
  1221.  
  1222.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  1223.     if (retVal != TRUE) {
  1224.     (void) MessageBox(WindowFromDC(hDC),
  1225.         "Failed to set pixel format.",
  1226.         "OpenGL application error",
  1227.         MB_ICONERROR | MB_OK);
  1228.     exit(1);
  1229.     }
  1230. }
  1231.  
  1232. LRESULT APIENTRY
  1233. WndProc(
  1234.     HWND hWnd,
  1235.     UINT message,
  1236.     WPARAM wParam,
  1237.     LPARAM lParam)
  1238. {
  1239.     int needRedraw = 0;
  1240.  
  1241.     /* Handle messages to which the application must respond */
  1242.     switch (message) {
  1243.     case WM_CREATE:
  1244.     hDC = GetDC(hWnd);
  1245.     setupDC(hDC);
  1246.     setupPalette(hDC);
  1247.     hGLRC = wglCreateContext(hDC);
  1248.     wglMakeCurrent(hDC, hGLRC);
  1249.     init(hDC);
  1250.     return 0;
  1251.     case WM_DESTROY:
  1252.     if (hGLRC) {
  1253.         wglMakeCurrent(NULL, NULL);
  1254.         wglDeleteContext(hGLRC);
  1255.     }
  1256.     idleFunc = NULL;
  1257.     ReleaseDC(hWnd, hDC);
  1258.     PostQuitMessage(0);
  1259.     return 0;
  1260.     case WM_SIZE:
  1261.     if (hGLRC) {
  1262.         winWidth = (int) LOWORD(lParam);
  1263.         winHeight = (int) HIWORD(lParam);
  1264.         resize(hDC);
  1265.         return 0;
  1266.     }
  1267.     break;
  1268.     case WM_PALETTECHANGED:
  1269.     if (hPalette != NULL && (HWND) wParam != hWnd) {
  1270.         UnrealizeObject(hPalette);
  1271.         SelectPalette(hDC, hPalette, FALSE);
  1272.         RealizePalette(hDC);
  1273.         redraw(hDC);
  1274.         return 0;
  1275.     }
  1276.     break;
  1277.     case WM_QUERYNEWPALETTE:
  1278.     if (hPalette != NULL) {
  1279.         UnrealizeObject(hPalette);
  1280.         SelectPalette(hDC, hPalette, FALSE);
  1281.         RealizePalette(hDC);
  1282.         redraw(hDC);
  1283.         return TRUE;
  1284.     }
  1285.     break;
  1286.     case WM_PAINT:
  1287.     if (hGLRC) {
  1288.         PAINTSTRUCT ps;
  1289.         BeginPaint(hWnd, &ps);
  1290.         redraw(hDC);
  1291.         EndPaint(hWnd, &ps);
  1292.         return 0;
  1293.     }
  1294.     break;
  1295.     case WM_LBUTTONDOWN:
  1296.     if (hGLRC) {
  1297.         int x = (int) LOWORD(lParam);
  1298.         int y = (int) HIWORD(lParam);
  1299.         SetCapture(hWnd);
  1300.         startMotion(hDC, 0, 1, x, y);
  1301.         return 0;
  1302.     }
  1303.     break;
  1304.     case WM_LBUTTONUP:
  1305.     if (hGLRC) {
  1306.         int x = (int) LOWORD(lParam);
  1307.         int y = (int) HIWORD(lParam);
  1308.         ReleaseCapture();
  1309.         stopMotion(hDC, 0, 1, x, y);
  1310.         return 0;
  1311.     }
  1312.     break;
  1313.     case WM_MOUSEMOVE:
  1314.     if (hGLRC) {
  1315.         int x = (int) LOWORD(lParam);
  1316.         int y = (int) HIWORD(lParam);
  1317.         trackMotion(hDC, 0, x, y);
  1318.     }
  1319.     break;
  1320.     case WM_KEYDOWN:
  1321.     switch ( wParam )
  1322.     {
  1323.     case VK_LEFT:
  1324.         left_pressed = TRUE;
  1325.             needRedraw = 1;
  1326.         break;
  1327.     case VK_RIGHT:
  1328.         right_pressed = TRUE;
  1329.             needRedraw = 1;
  1330.         break;
  1331.     case VK_UP:
  1332.         up_pressed = TRUE;
  1333.             needRedraw = 1;
  1334.         break;
  1335.     case VK_DOWN:
  1336.         down_pressed = TRUE;
  1337.             needRedraw = 1;
  1338.         break;
  1339.     }
  1340.         if (needRedraw) {
  1341.             userSettings(0);
  1342.             doRedraw(hDC);
  1343.         }
  1344.     break;
  1345.     case WM_KEYUP:
  1346.     switch ( wParam )
  1347.     {
  1348.     case VK_LEFT:
  1349.         left_pressed = FALSE;
  1350.             needRedraw = 1;
  1351.         break;
  1352.     case VK_RIGHT:
  1353.         right_pressed = FALSE;
  1354.             needRedraw = 1;
  1355.         break;
  1356.     case VK_UP:
  1357.         up_pressed = FALSE;
  1358.             needRedraw = 1;
  1359.         break;
  1360.     case VK_DOWN:
  1361.         down_pressed = FALSE;
  1362.             needRedraw = 1;
  1363.         break;
  1364.     }
  1365.         if (needRedraw) {
  1366.             userSettings(0);
  1367.             doRedraw(hDC);
  1368.         }
  1369.     break;
  1370.     case WM_CHAR:    
  1371.     switch ((int)wParam) {
  1372.     case 27: /* Escape */
  1373.         PostQuitMessage(0);
  1374.         break;
  1375.     }
  1376.     if (needRedraw) {
  1377.         userSettings(1);
  1378.         doRedraw(hDC);
  1379.     }
  1380.     return 0;
  1381.     break;
  1382.     case WM_CONTEXTMENU:
  1383.     {
  1384.         TrackPopupMenu(hMainPup, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1385.                 LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
  1386.         break;
  1387.         }
  1388.     case WM_COMMAND:
  1389.     {
  1390.         switch (LOWORD(wParam)) {
  1391.         case IDM_DITHER_ENABLED:
  1392.         dither = TRUE;
  1393.         userSettings( 1 );
  1394.         redraw( hDC );
  1395.         break;
  1396.         case IDM_DITHER_DISABLED:
  1397.         dither = FALSE;
  1398.         userSettings( 1 );
  1399.         redraw( hDC );
  1400.         break;
  1401.         case IDM_SHADE_FLAT:
  1402.         shade = GL_FLAT;
  1403.         userSettings( 1 );
  1404.         redraw( hDC );
  1405.         break;
  1406.         case IDM_SHADE_SMOOTH:
  1407.         shade = GL_SMOOTH;
  1408.         userSettings( 1 );
  1409.         redraw( hDC );
  1410.         break;
  1411.         case IDM_TEXTURE_DISABLED:
  1412.         doTexture = FALSE;
  1413.         userSettings(1);
  1414.         redraw(hDC);
  1415.         break;
  1416.         case IDM_TEXTURE_ENABLED:
  1417.         doTexture = TRUE;
  1418.         userSettings(1);
  1419.         redraw(hDC);
  1420.         break;
  1421.         case IDM_VXCULL_DISABLED:
  1422.         vxCull = FALSE;
  1423.         userSettings(1);
  1424.         redraw(hDC);
  1425.         break;
  1426.         case IDM_VXCULL_ENABLED:
  1427.         vxCull = TRUE;
  1428.         userSettings(1);
  1429.         redraw(hDC);
  1430.         break;
  1431.         case IDM_LIGHT_DISABLED:
  1432.         doLighting = FALSE;
  1433.         userSettings(1);
  1434.         redraw(hDC);
  1435.         break;
  1436.         case IDM_LIGHT_ENABLED:
  1437.         doLighting = TRUE;
  1438.         userSettings(1);
  1439.         redraw(hDC);
  1440.         break;
  1441.         case IDM_PMODE_TSTRIP:
  1442.         case IDM_PMODE_QSTRIP:
  1443.         case IDM_PMODE_LSTRIP:
  1444.         case IDM_PMODE_TRIANGLES:
  1445.         case IDM_PMODE_QUADS:
  1446.         case IDM_PMODE_LINES:
  1447.         case IDM_PMODE_POINTS:
  1448.         case IDM_PMODE_LLOOP:
  1449.         case IDM_PMODE_TFAN:
  1450.         case IDM_PMODE_POLYGON:
  1451.         primMode = LOWORD(wParam) - IDM_PMODE_TSTRIP;
  1452.         userSettings(1);
  1453.         redraw(hDC);
  1454.         break;
  1455.         case IDM_DMODE_DRAW_ARRAYS:
  1456.         case IDM_DMODE_DRAW_ELEMENTS:
  1457.         case IDM_DMODE_VERTEX:
  1458.         drawMode = LOWORD(wParam) - drawModeIDMs[firstDrawMode];
  1459.         userSettings(1);
  1460.         redraw(hDC);
  1461.         break;
  1462.         case IDM_OUTLINE_ENABLED:
  1463.         doOutline = TRUE;
  1464.         userSettings(1);
  1465.         redraw(hDC);
  1466.         break;
  1467.         case IDM_OUTLINE_DISABLED:
  1468.         doOutline = FALSE;
  1469.         userSettings(1);
  1470.         redraw(hDC);
  1471.         break;
  1472.         case IDM_TEXENV_REPLACE:
  1473.         case IDM_TEXENV_MODULATE:
  1474.         case IDM_TEXENV_ADD:
  1475.         case IDM_TEXENV_BLEND:
  1476.         /* In Color Index mode, change the texture if the environment
  1477.          * changes!
  1478.          */
  1479.         if (!rgba && texenv != (int)wParam) {
  1480.             needTexImage = TRUE;
  1481.         }
  1482.         texenv = wParam;
  1483.         userSettings( 1 );
  1484.         redraw( hDC );
  1485.         break;
  1486.         case IDM_APPLICATION_EXIT:
  1487.         PostQuitMessage(0);
  1488.         break;
  1489.         }
  1490.     }
  1491.     break;
  1492.     default:
  1493.     break;
  1494.     }
  1495.  
  1496.     /* Make sure all messages get returned to Windows. */
  1497.     return DefWindowProc(hWnd, message, wParam, lParam);
  1498. }
  1499.  
  1500. int APIENTRY
  1501. WinMain(
  1502.     HINSTANCE hCurrentInst,
  1503.     HINSTANCE hPreviousInst,
  1504.     LPSTR lpszCmdLine,
  1505.     int nCmdShow)
  1506. {
  1507.     WNDCLASS wndClass;
  1508.     HWND hWnd;
  1509.     MSG msg;
  1510.  
  1511.     /* Define and register the window class */
  1512.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  1513.     wndClass.lpfnWndProc = WndProc;
  1514.     wndClass.cbClsExtra = 0;
  1515.     wndClass.cbWndExtra = 0;
  1516.     wndClass.hInstance = hCurrentInst;
  1517.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  1518.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  1519.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  1520.     wndClass.lpszMenuName = NULL;
  1521.     wndClass.lpszClassName = className;
  1522.  
  1523.     RegisterClass(&wndClass);
  1524.  
  1525.     {
  1526.       HDC hdc = GetDC( 0 );
  1527.       int bpp = GetDeviceCaps( hdc, BITSPIXEL );
  1528.  
  1529.       if ( bpp <= 8 ) rgba = 0;
  1530.       else rgba = 1;
  1531.  
  1532.       ReleaseDC( 0, hdc );
  1533.     }
  1534.  
  1535.     /* Get the size of the screen */
  1536.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  1537.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  1538.  
  1539.     /* Create a window of the previously defined class */
  1540.     hWnd = CreateWindow(
  1541.     className,        /* Window class's name */
  1542.     windowName,        /* Title bar text */
  1543.     WS_OVERLAPPEDWINDOW |    /* The window's style */
  1544.     WS_CLIPCHILDREN |
  1545.     WS_CLIPSIBLINGS,
  1546.     winX, winY,        /* X position */
  1547.     winWidth, winHeight,    /* Size */
  1548.     NULL,            /* Parent window's handle */
  1549.     NULL,            /* Menu handle */
  1550.     hCurrentInst,        /* Instance handle */
  1551.     NULL);            /* No additional data */
  1552.  
  1553.     /* Create a popup menu */
  1554.     {
  1555.     unsigned int i;
  1556.     hMainPup = CreatePopupMenu();
  1557.  
  1558.     hTexturePup = CreatePopupMenu();
  1559.     AppendMenu(hTexturePup, MF_STRING, IDM_TEXTURE_ENABLED, "Enabled");
  1560.     AppendMenu(hTexturePup, MF_STRING, IDM_TEXTURE_DISABLED, "Disabled");
  1561.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hTexturePup, "texture");
  1562.  
  1563.     hTexEnvPup = CreatePopupMenu();
  1564.     AppendMenu( hTexEnvPup, MF_STRING, IDM_TEXENV_REPLACE, "Replace" );
  1565.     AppendMenu( hTexEnvPup, MF_STRING, IDM_TEXENV_MODULATE, "Modulate" );
  1566.     AppendMenu( hTexEnvPup, MF_STRING, IDM_TEXENV_BLEND, "Blend" );
  1567.     AppendMenu( hTexEnvPup, MF_STRING, IDM_TEXENV_ADD, "Add" );
  1568.     AppendMenu( hMainPup, MF_POPUP|MF_STRING, (UINT) hTexEnvPup, "tex env" );
  1569.     if (rgba) {
  1570.         EnableMenuItem(hTexEnvPup, IDM_TEXENV_ADD,
  1571.                MF_BYCOMMAND|MF_GRAYED);
  1572.     } else {
  1573.         EnableMenuItem(hTexEnvPup, IDM_TEXENV_MODULATE,
  1574.                MF_BYCOMMAND|MF_GRAYED);
  1575.         EnableMenuItem(hTexEnvPup, IDM_TEXENV_BLEND,
  1576.                MF_BYCOMMAND|MF_GRAYED);
  1577.     }
  1578.  
  1579.     hVxCullPup = CreatePopupMenu();
  1580.     AppendMenu(hVxCullPup, MF_STRING, IDM_VXCULL_ENABLED, "Enabled");
  1581.     AppendMenu(hVxCullPup, MF_STRING, IDM_VXCULL_DISABLED, "Disabled");
  1582.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hVxCullPup, "vx cull");
  1583.  
  1584.     hLightPup = CreatePopupMenu();
  1585.     AppendMenu(hLightPup, MF_STRING, IDM_LIGHT_ENABLED, "Enabled");
  1586.     AppendMenu(hLightPup, MF_STRING, IDM_LIGHT_DISABLED, "Disabled");
  1587.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hLightPup, "lighting");
  1588.  
  1589.     hShadePup = CreatePopupMenu();
  1590.     AppendMenu( hShadePup, MF_STRING, IDM_SHADE_FLAT, "Flat" );
  1591.     AppendMenu( hShadePup, MF_STRING, IDM_SHADE_SMOOTH, "Smooth" );
  1592.     AppendMenu( hMainPup, MF_POPUP|MF_STRING, (UINT) hShadePup, "shade model" );
  1593.  
  1594.     hOutlinePup = CreatePopupMenu();
  1595.     AppendMenu(hOutlinePup, MF_STRING, IDM_OUTLINE_ENABLED, "Enabled");
  1596.     AppendMenu(hOutlinePup, MF_STRING, IDM_OUTLINE_DISABLED, "Disabled");
  1597.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hOutlinePup, "outline");
  1598.  
  1599.     hPmodePup = CreatePopupMenu();
  1600.     for (i=0; i < numPrimModes; i++) {
  1601.         AppendMenu(hPmodePup, MF_STRING, 
  1602.             primModeIDMs[i], primModeStrings[i]);
  1603.     }
  1604.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hPmodePup, "prim mode");
  1605.  
  1606.     hDmodePup = CreatePopupMenu();
  1607.     for (i=0; i < numDrawModes; i++) {
  1608.         AppendMenu(hDmodePup, MF_STRING, 
  1609.             drawModeIDMs[i], drawModeStrings[i]);
  1610.     }
  1611.     AppendMenu(hMainPup, MF_POPUP|MF_STRING, (UINT) hDmodePup, "draw mode");
  1612.  
  1613.     hDitherPup = CreatePopupMenu();
  1614.     AppendMenu( hDitherPup, MF_STRING, IDM_DITHER_ENABLED, "Enabled" );
  1615.     AppendMenu( hDitherPup, MF_STRING, IDM_DITHER_DISABLED, "Disabled" );
  1616.     AppendMenu( hMainPup, MF_POPUP|MF_STRING, (UINT) hDitherPup, "dither" );
  1617.  
  1618.     AppendMenu(hMainPup, MF_SEPARATOR, 0, NULL);
  1619.     AppendMenu(hMainPup, MF_STRING, IDM_APPLICATION_EXIT, "Exit");
  1620.     }
  1621.     userSettings(1);
  1622.  
  1623.     /* Map the window to the screen */
  1624.     ShowWindow(hWnd, nCmdShow);
  1625.  
  1626.     /* Force the window to repaint itself */
  1627.     UpdateWindow(hWnd);
  1628.  
  1629.     /* Message loop */
  1630.     while (1) {
  1631.     while (idleFunc &&
  1632.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  1633.     {
  1634.         (*idleFunc)(hDC);
  1635.     }
  1636.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  1637.         return msg.wParam;
  1638.     }
  1639.     TranslateMessage(&msg);
  1640.     DispatchMessage(&msg);
  1641.     }
  1642. }
  1643. 
  1644.